package knapsackProblem;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import almm.GeneralizedState;
import almm.State;

public class ControlDecision implements almm.ControlDecision {

	private Set<Task> tasks;
	private Map<GeneralizedState, PossibleDecisions> possibleDecisions;

	protected ControlDecision(Set<Task> tasks) {
		this.tasks = tasks;
		this.possibleDecisions = new HashMap<GeneralizedState, PossibleDecisions>();
	}

	protected Set<Task> getTasks() {
		return tasks;
	}

	private PossibleDecisions managePossibleDecisions(GeneralizedState s) {
		if (!this.possibleDecisions.containsKey(s)) {
			Set<Task> tmpPossibleDecisions = this.generatePossibleDecisions(s);
			this.possibleDecisions.put(s, new PossibleDecisions(
					tmpPossibleDecisions));
		}
		return possibleDecisions.get(s);
	}

	public Set<Task> getPossibleDecisions(GeneralizedState s) {
		return this.managePossibleDecisions(s).getPossibleDecisions();
	}

	public Task getDecision(GeneralizedState s) {
		return this.managePossibleDecisions(s).decide();
	}

//	protected abstract Set<Task> generatePossibleDecisions(GeneralizedState s);
	protected Set<Task> generatePossibleDecisions(almm.GeneralizedState s) {		
		Set<State> doneTasks = s.getProperState().getCurrentState();
		
				Set<Task> possibleDecisions = new HashSet<Task>(getTasks()) ;
				Iterator<Task> iterator = getTasks().iterator();
				while (iterator.hasNext()) {
					Task currentTask = iterator.next();
					if (doneTasks.contains(currentTask))
						possibleDecisions.remove(currentTask);
				}
				return possibleDecisions;
	}
	
	class PossibleDecisions {
		private Set<Task> possibleDecisions;

		public Set<Task> getPossibleDecisions() {
			return possibleDecisions;
		}

		protected PossibleDecisions(Set<Task> possibleDecisions) {
			this.possibleDecisions = possibleDecisions;
		}

		public Task decide() {
			List<Task> taskList = new ArrayList<Task>(possibleDecisions.size());
			for (Task task : possibleDecisions) {
				taskList.add(task);
			}
			Collections.sort(taskList);

			return taskList.get(0);
		}
	}
}